package xauth

import (
	"time"

	"gitee.com/xiaoyutab/xgotool/optional/xcache"
	"gitee.com/xiaoyutab/xgotool/xnum"
)

// 获取我的下级用户
//
//	uid	用户ID 1-超管用户，此用户会直接返回nil，所以需要外部判断如果uid==1就直接不查询此条件
//	typ	权限来源
//	sf	返回的下级ID中，是否需要包含自身 true-包含自身 false-不含自身
func GetUserChild(uid uint, typ uint, sf bool) []uint {
	if uid == 0 || uid == 1 {
		return nil
	}
	cache_key := xcache.Key("xauth.get-user-child", uid, typ)
	mod := []uint{}
	if xcache.Exists(cache_key) {
		if err := xcache.GetStruct(cache_key, &mod); err == nil {
			return mod
		}
	}
	// 从数据库中进行查询
	rep_id := []uint{}
	temp_id := []uint{uid}
	for {
		// 获取用户下级ID
		temp := getUserChildBySupId(temp_id, typ, rep_id)
		if len(temp) == 0 {
			break
		}
		rep_id = append(rep_id, temp...)
		temp_id = temp
	}
	// 循环排重
	new_uid := []uint{}
	if sf {
		new_uid = []uint{uid}
	}
	for i := 0; i < len(rep_id); i++ {
		if rep_id[i] == uid || xnum.InArray(rep_id[i], new_uid) {
			continue
		}
		new_uid = append(new_uid, rep_id[i])
	}
	// 排除自身uid【将传入的uid排除出去】
	xcache.SetStructExt(cache_key, new_uid, time.Hour*24*30)
	return new_uid
}

// 获取用户的下级用户
//
//	uid	用户ID列表
//	typ	权限来源
//	exp	忽略用户ID列表
func getUserChildBySupId(uid []uint, typ uint, exp []uint) []uint {
	if len(uid) == 0 {
		return nil
	}
	if exp == nil {
		exp = []uint{}
	}
	cache_key := xcache.Key("xauth.get-user-child-by-sup-id", uid, typ, exp)
	mod := []uint{}
	if xcache.Exists(cache_key) {
		if err := xcache.GetStruct(cache_key, &mod); err == nil {
			return mod
		}
		mod = []uint{}
	}
	db := _default.DB.Table(_default.UserChildName).
		Select("user_id").
		Where("type", typ).
		Where("superior_id in ?", uid).
		Where("user_id != 1"). // 排除超级管理员的ID
		Where("user_id not in ?", uid)
	if len(exp) > 0 {
		db = db.Where("user_id not in ?", exp)
	}
	// 从数据库中进行查询
	err := db.
		Find(&mod).
		Error
	if err != nil {
		errFun("下级用户获取失败", err)
		return nil
	}
	xcache.SetStructExt(cache_key, mod, time.Hour*24*30)
	return mod
}

// 获取我的直属下级用户列表
//
//	uid	我的ID列表
//	typ	所属平台ID
func GetUserChildOnly(uid, typ uint) []uint {
	if uid == 0 || uid == 1 {
		return nil
	}
	return getUserChildBySupId([]uint{uid}, typ, nil)
}
